#include "stdafx.h"
#include "AspectInstaller.h"

CAspectInstaller::CAspectInstaller()
{
}

CAspectInstaller CAspectInstaller::instance;
Vtlb CAspectInstaller::aspectInstallerVtlb;

ASPECTOR_API 
CAspectInstaller* CAspectInstaller::Instance()
{
	return &instance;
}

void CAspectInstaller::InstallAdvice(void *_pObject)
{
	CObject* pObject = reinterpret_cast<CObject*>(_pObject);
	Vtlb* vtlb = pObject->pVtbl;
	this->objects.insert(std::make_pair(pObject,vtlb));
	pObject->pVtbl = &aspectInstallerVtlb;
}

int __stdcall CAspectInstaller::Invoke(CObject* pObject,int vtlbIndex,va_list parametersStack)
{
	Vtlb* vtlb = this->objects[pObject];
	std::list<IMethodInterceptorAdvice*>::iterator pIt = this->aspects.begin();
	while ( pIt!=this->aspects.end() )
	{
		(*pIt)->Before();
		pIt++;
	}

	// Perform invocation of the target method
	int returnValue = 0;
	int stackSize = 2;
	for(int i=1;i<=stackSize;i++)
	{
		int value = (int)parametersStack[sizeof(int)*(stackSize-i)];
		__asm push value;
	}
	__asm push pObject;
	int (__stdcall * VFunc)(CObject* pObject) = vtlb->VFunc[vtlbIndex];
	char* espPointer = NULL;
	__asm mov espPointer,esp;
	__asm call VFunc;
	__asm mov returnValue, eax;

	pIt = this->aspects.begin();
	while ( pIt!=this->aspects.end() )
	{
		(*pIt)->After();
		pIt++;
	}
	return returnValue;
}


